﻿
#region Using Directives.

using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using ActiproSoftware.SyntaxEditor;
using System.Text;
using RWXMLEdit.Common;

#endregion

namespace S3.WMDSLEditor.Common
{
    public class Functions
    {
        #region Public Methods.

        public static bool OpenViewDocument(XmlDocument document, string viewClassName, out Document viewDocument)
        {
            viewDocument = new Document();

            try
            {
                var namespaceManager = new XmlNamespaceManager(document.NameTable);

                namespaceManager.AddNamespace("WmBofDSL", "http://schemas.microsoft.com/dsltools/WmBofDSL");

                string xPath = string.Format("//WmBofDSL:Types/WmBofDSL:viewClass[@Name='{0}']", viewClassName);

                XmlNode node = document.SelectSingleNode(xPath, namespaceManager);

                if(node != null)
                {
                    string xml = FormatXml(node.OuterXml);

                    viewDocument.Text = xml;

                    return true;
                }

                return false;
            }
            catch (Exception)
            {
                return false;
            }
        }

        public static bool OpenWmdslFile(string wmdslFilePath, out XmlDocument document, out string backupPath)
        {
            document = new XmlDocument();
            backupPath = string.Empty;
            
            try
            {
                var reader = new FileStream(wmdslFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

                document.Load(reader);

                //Save a backup of the file
                string personalFolder = GetPersonalFolder();

                string filename = Path.GetFileNameWithoutExtension(wmdslFilePath);

                backupPath = string.Format("{0}\\{1}.wmdsl.bak", personalFolder, filename);

                document.Save(backupPath);

                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        public static bool SaveWmdslFile(string viewClassName, XmlDocument document, string xml, string wmdslPath, out string errorMsg)
        {
            errorMsg = string.Empty;

            if (string.IsNullOrEmpty(wmdslPath))
                return false;

            try
            {
                var namespaceManager = new XmlNamespaceManager(document.NameTable);

                namespaceManager.AddNamespace("WmBofDSL", "http://schemas.microsoft.com/dsltools/WmBofDSL");

                string xPath = string.Format("//WmBofDSL:viewClass[@Name='{0}']", viewClassName);

                XmlNode editNode = document.SelectSingleNode(xPath, namespaceManager);

                XmlDocumentFragment fragment = document.CreateDocumentFragment();

                fragment.InnerXml = xml;

                if (editNode != null && editNode.ParentNode != null)
                {
                    editNode.ParentNode.ReplaceChild(fragment, editNode);
                }
                else
                {
                    return false;
                }

                document.InnerXml = document.InnerXml.Replace("xmlns=\"\"", "");

                document.Save(wmdslPath);

                return true;
            }
            catch (Exception msg)
            {
                errorMsg = msg.Message;
                return false;
            }
        }

        public static bool SaveWmdslFileAs(string viewClassName, XmlDocument document, string xml, string wmdslPath, string saveAsPath)
        {
            string msg;

            if(string.IsNullOrEmpty(viewClassName) && string.IsNullOrEmpty(xml))
            {
                try
                {
                    FileInfo fi = new FileInfo(wmdslPath);

                    fi.CopyTo(saveAsPath, true);

                    return true;
                }
                catch (Exception)
                {
                    return false;
                }
            }
            
            if (SaveWmdslFile(viewClassName, document, xml, saveAsPath, out msg))
            {
                return true;
            }

            return false;
        }

        public static bool BackupWmdslFile(string originalPath, string backupPath)
        {
            try
            {
                FileInfo fi = new FileInfo(originalPath);
                
                fi.CopyTo(backupPath);

                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        public static bool DeleteTempFiles(List<string> files)
        {
            try
            {
                foreach (string file in files)
                {
                    File.Delete(file);
                }
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        public static string GetTemporaryFileName(string extn)
        {
            if (!extn.StartsWith("."))
            {
                extn = string.Format(".{0}", extn);
            }

            return string.Format("{0}{1}{2}", Path.GetTempPath(), Guid.NewGuid(), extn);
        }

        public static List<string> GetAllViewNames(XmlDocument document)
        {
            var retval = new List<string>();
            XmlNodeList nodeList = document.GetElementsByTagName("viewClass");

            foreach (XmlNode node in nodeList)
            {
                if (node.Attributes != null)
                {
                    retval.Add(node.Attributes["Name"].Value);
                }
            }

            return retval;
        }

        public static List<string> CreateStringArrayLines(string text)
        {
            var lines = new List<string>();

            string[] temp = text.Split('\n');

            lines.AddRange(temp);

            return lines;
        }

        public static bool ValidateKeyChar(char key)
        {
            // Try converting the introduced char value to a byte value
            byte i;
            bool parsed = byte.TryParse(key.ToString(), out i);
            bool val;

            //If convresion succeeded, show allow character.
            if (parsed)
            {
                val = false;
            }
            // If the conversion did not succeed, check if the pressed
            // button was Backspace (char code is 8) or Delete (char code is 46).
            else
            {
                switch (Convert.ToInt32(key))
                {
                    case 8:
                        val = false;  // If Backspace, allow char.
                        break;
                    case 46:
                        val = false;  // If Delete, allow char.
                        break;
                    default:
                        val = true;
                        break;
                }
            }
            return val;
        }

        public static bool IsFileReadOnly(string path)
        {
            if (string.IsNullOrEmpty(path))
                return false;

            FileInfo file = new FileInfo(path);
                      
            if ((file.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
            {
                return true;
            }

            return false;
        }

        public static string InvertCasing(string text)
        {
            if (text == null)
                return string.Empty;

            StringBuilder sb = new StringBuilder();
            foreach (char c in text)
            {
                if (Char.IsLower(c))
                    sb.Append(Char.ToUpper(c));
                else if (Char.IsUpper(c))
                    sb.Append(Char.ToLower(c));
                else
                {
                    sb.Append(c);
                }
            }

            return sb.ToString();
        }

        /// <summary>
        /// Formats the provided XML so it's indented and humanly-readable.
        /// </summary>
        /// <param name="inputXml">The input XML to format.</param>
        /// <returns></returns>
        public static string FormatXml(string inputXml)
        {
            XmlDocument document = new XmlDocument();

            if (inputXml.Contains("xmlns=\"http://schemas.microsoft.com/dsltools/WmBofDSL\""))
            {
                inputXml = inputXml.Replace("xmlns=\"http://schemas.microsoft.com/dsltools/WmBofDSL\"", "");
            }

            document.Load(new StringReader(inputXml));

            StringBuilder builder = new StringBuilder();

            XmlWriterSettings settings = new XmlWriterSettings();
            settings.OmitXmlDeclaration = true;
            //settings.ConformanceLevel = ConformanceLevel.Fragment;
            settings.Indent = true;

            XmlWriter writer = XmlWriter.Create(new StringWriterEx(Encoding.UTF8, builder), settings);

            document.Save(writer);

            writer.Close();

            return builder.ToString();
        }

        #endregion

        #region Private Methods.

        private static string GetPersonalFolder()
        {
            return Environment.GetFolderPath(Environment.SpecialFolder.Personal);
        }

        #endregion
    }
}